package org.conan.groupapp.util;

import java.io.IOException;
import java.sql.Clob;
import java.sql.SQLException;
import java.text.Collator;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.RandomUtils;


import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * 公共服务类<br>
 * @author phoenix
 * @date 2009-3-23
 */
@SuppressWarnings("unchecked")
public final class CommonUtil {

	/**
	 * 数据类型--Integer
	 */
	public static final String DATATYPE_INTEGER = "Integer";
	/**
	 * 数据类型--Long
	 */
	public static final String DATATYPE_LONG = "Long";
	/**
	 * 数据类型--Short
	 */
	public static final String DATATYPE_SHORT = "Short";
	/**
	 * 数据类型--Float
	 */
	public static final String DATATYPE_FLOAT = "Float";
	/**
	 * 数据类型--Double
	 */
	public static final String DATATYPE_DOUBLE = "Double";
	/**
	 * 数据类型--Date（只有日期部分）
	 */
	public static final String DATATYPE_DATE = "Date";
	/**
	 * 数据类型--Date（只有时间部分）
	 */
	public static final String DATATYPE_TIME = "Time";
	/**
	 * 数据类型--Date（完整）
	 */
	public static final String DATATYPE_DATETIME = "Datetime";
	//一年中月的个数
	private static final int MONTHS_OF_YEAR = 12;
	//一年中日的个数
	private static final int DAYS_OF_YEAR = 365;
	//闰年中日的个数
	private static final int DAYS_OF_SPECIAL_YEAR = 366;
	//默认的日期格式
	private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
	//默认的时间格式
	private static final String DEFAULT_TIME_FORMAT = "H:mm:ss";
	//默认的完整日期格式
	private static final String DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd H:mm:ss";
	
	private static final NumberFormat nf = NumberFormat.getInstance();

	/**
	 * 将数字对象转换成字符串<br>
	 * @param number 需转换的数字对象
	 * @param group 是否分组
	 * @param maxFD 小数部分的最大位数
	 * @return 转换出来的字符串
	 */
	public static String num2str(Number number, boolean group, int maxFD) {
		nf.setGroupingUsed(group);
		nf.setMaximumFractionDigits(maxFD);
		return nf.format(number);
	}
	
	/**
	 * 将对象转换成字符串<br>
	 * @param object 需转换的对象
	 * @param defValue 默认值
	 * @return 转换出来的字符串
	 */
	public static String convertToString(Object object, String defValue) {
		return convertToString(object, defValue, null);
	}
	
	/**
	 * 将对象转换成字符串<br>
	 * @param object 需转换的对象
	 * @param defValue 默认值
	 * @param dateMode 日期模式，分三种模式:<br>
	 * 1. Date模式，只有日期部分（"yyyy-M-d"）<br>
	 * 2. Time模式，只有时间部分（"H:mm:ss"）<br>
	 * 3. Datetime模式，既有日期部分，又有时间部分，格式（"yyyy-M-d H:mm:ss"），默认模式
	 * @return 转换出来的字符串
	 */
	public static String convertToString(Object object, String defValue, String dateMode) {
		if(object == null) return defValue;
		if(object instanceof Number) {//object是数字类型
			return num2str((Number) object, false, 4);
		}
		if(object instanceof Date) {
			if(DATATYPE_DATE.equals(dateMode))
				return convertDate((Date) object);
			else if(DATATYPE_TIME.equals(dateMode))
				return convertTime((Date) object);
			else return convertDateTime((Date) object);
		}
		try {
			if(object instanceof Clob) {
				Clob clob = (Clob) object;
				int len = (clob.length() > 1000)? 1000: (int) clob.length();
				return clob.getSubString(1, len);
			}
		} catch (SQLException e) {
			return null;
		}
		return object.toString();
	}
	
	/**
	 * 将对象转换成字符串(为了方便在页面上的显示,将空的对象与空的字符串转换成"&nbsp;")<br>
	 * @param object 需转换的对象
	 * @return 转换出来的字符串
	 */
	public static String convertToString(Object object) {
		String str = convertToString(object, "&nbsp;");
		if(str.equals("")) return "&nbsp;";
		else return str;
	}
	
	/**
	 * 将对象数组转换成字符串<br>
	 * @param array 需转换的对象数组
	 * @param space 间隔符
	 * @return 转换出来的字符串
	 */
	public static String convertToString(Object[] array, String space) {
		if(array == null || array.length == 0) return "";
		StringBuffer str = new StringBuffer(convertToString1(array[0]));
		for(int i=1;i<array.length;i++)
			str.append(convertToString1(space)).append(convertToString1(array[i]));
		return str.toString();
	}
	
	/**
	 * 将对象集合转换成字符串<br>
	 * @param array 需转换的对象集合
	 * @param space 间隔符
	 * @return 转换出来的字符串
	 */
	public static String convertToString(Collection collection, String space) {
		if(isNullList(collection)) return "";
		return convertToString(collection.toArray(), space);
	}
	
	/**
	 * 将对象转换成字符串(将空的对象转换成空的字符串)<br>
	 * @param object 需转换的对象
	 * @return 转换出来的字符串
	 */
	public static String convertToString1(Object object) {
		return convertToString(object, "");
	}

	/**
	 * 将数字对象转换成百分比字符串(小数点后精确到4位)<br>
	 * 将非数字对象转换成空的字符串<br>
	 * @param object 需转换的对象
	 * @return 转换出来的字符串
	 */
	public static String convertToPercent(Object object) {
		if(object instanceof Number) {//object是数字类型
			NumberFormat pnf = NumberFormat.getPercentInstance();
			pnf.setGroupingUsed(false);
			pnf.setMaximumFractionDigits(2);
			return pnf.format(object);
		}
		return "";
	}

	/**
	 * 将日期对象按照指定的格式转换成字符串(将空的对象转换成空的字符串)<br>
	 * @param date 需转换的日期对象
	 * @param format 转换格式
	 * @return 转换出来的字符串
	 */
	public static String convertDate(Date date, String format) {
		if(date == null) return "";
		DateFormat df = new SimpleDateFormat(format);
		return df.format(date);
	}

	/**
	 * 将日期对象按照默认日期格式(yyyy-M-d)转换成字符串(将空的对象转换成空的字符串)<br>
	 * @param date 需转换的日期对象
	 * @return 转换出来的字符串
	 */
	public static String convertDate(Date date) {
		return convertDate(date, DEFAULT_DATE_FORMAT);
	}

	/**
	 * 将日期对象按照默认时间格式(H:mm:ss)转换成字符串(将空的对象转换成空的字符串)<br>
	 * @param time 需转换的日期对象
	 * @return 转换出来的字符串
	 */
	public static String convertTime(Date time) {
		return convertDate(time, DEFAULT_TIME_FORMAT);
	}

	/**
	 * 将日期对象按照默认日期时间格式(yyyy-M-d H:mm:ss)转换成字符串(将空的对象转换成空的字符串)<br>
	 * @param dateTime 需转换的日期对象
	 * @return 转换出来的字符串
	 */
	public static String convertDateTime(Date dateTime) {
		return convertDate(dateTime, DEFAULT_DATETIME_FORMAT);
	}

	/**
	 * 将日期对象按照长格式(如:2007年1月10日)转换成字符串(将空的对象转换成空的字符串)<br>
	 * @param date 需转换的日期对象
	 * @return 转换出来的字符串
	 */
	public static String convertDateInLongMod(Date date) {
		if(date == null) return "";
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int year = calendar.get(Calendar.YEAR);
		int month = calendar.get(Calendar.MONTH);
		int day = calendar.get(Calendar.DATE);
		int weekday = calendar.get(Calendar.DAY_OF_WEEK);
		StringBuffer dateString = new StringBuffer();
		dateString.append(year);
		dateString.append("年");
		dateString.append(month + 1);
		dateString.append("月");
		dateString.append(day);
		dateString.append("日 星期");
		switch(weekday) {
			case 1: {
				dateString.append("日");
				break;
			}
			case 2: {
				dateString.append("一");
				break;
			}
			case 3: {
				dateString.append("二");
				break;
			}
			case 4: {
				dateString.append("三");
				break;
			}
			case 5: {
				dateString.append("四");
				break;
			}
			case 6: {
				dateString.append("五");
				break;
			}
			case 7: {
				dateString.append("六");
				break;
			}
		}
		return dateString.toString();
	}
	
	/**
	 * 转换数据类型<br>
	 * String与Integer/Long/Short/Float/Double/Date之间的数据类型相互转换
	 * @param value 源数据
	 * @param clazz 目标类型
	 * @param dateMode 日期转换成字符串分三种模式:<br>
	 * 1. Date模式，只有日期部分（"yyyy-M-d"）<br>
	 * 2. Time模式，只有时间部分（"H:mm:ss"）<br>
	 * 3. Datetime模式，既有日期部分，又有时间部分，格式（"yyyy-M-d H:mm:ss"），默认模式
	 * @return 转换后的目标数据
	 */
	public static Object changeType(Object value, Class clazz, String dateMode) {
		if(value == null || clazz == null)
			return value;
		Class oldClazz = value.getClass();
		if(clazz.equals(oldClazz)) return value;
		else {
			if(clazz.equals(String.class)) {
				return convertToString(value, "", dateMode);
			} else if(value instanceof String) {
				String text = (String) value;
				try {
					if(clazz.equals(Integer.class))
						return new Integer(text);
					else if(clazz.equals(Long.class))
						return new Long(text);
					else if(clazz.equals(Short.class))
						return new Short(text);
					else if(clazz.equals(Float.class))
						return new Float(text);
					else if(clazz.equals(Double.class))
						return new Double(text);
					else if(clazz.equals(Date.class)) {
						Date newValue = null;
						if(isNullString(dateMode)) {
							try {
								newValue = DateFormat.getDateTimeInstance().parse(text);
							} catch (ParseException e) {
								try {
									newValue = DateFormat.getDateInstance().parse(text);
								} catch (ParseException e1) {
									try {
										newValue = DateFormat.getTimeInstance().parse(text);
									} catch (ParseException e2) {
									}
								}
							}
						} else {
							DateFormat df = DateFormat.getDateTimeInstance();
							if(DATATYPE_DATE.equals(dateMode))
								df = DateFormat.getDateInstance();
							if(DATATYPE_TIME.equals(dateMode))
								df = DateFormat.getTimeInstance();
							newValue = df.parse(text);
						}
						return newValue;
					} else return null;
				} catch (Exception e) {
					return null;
				}
			} else return value;
		}
	}
	
	/**
	 * 转换数据类型<br>
	 * String与Integer/Long/Short/Float/Double/Date之间的数据类型相互转换
	 * @param value 源数据
	 * @param clazz 目标类型
	 * @return 转换后的目标数据
	 */
	public static Object changeType(Object value, Class clazz) {
		return changeType(value, clazz, null);
	}

	/** 
	 * 获取日期对象的日期部分
	 * @param date 日期对象，默认为当前时间
	 * @author phoenix
	 */
	public static Date getDate(Date date) {
		if(date == null) date = new Date();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}
	

	/** 
	 * 打印异常的堆栈信息
	 * @param exception 异常
	 * @return 异常的堆栈信息
	 * @author phoenix
	 */
	public static String printErrorTrace(Throwable exception) {
		StringBuffer errorString = new StringBuffer();
		errorString.append(exception.toString()).append("\n");
		StackTraceElement[] trace = exception.getStackTrace();
		for (int i=0; i < trace.length; i++) {
			errorString.append(trace[i]).append("\n");
		}
		return errorString.toString();
	}
	
	/** 
	 * 在源字符串后面反复填充指定的字符串直到达到指定的长度
	 * @param source 源字符串
	 * @param fill 填充的字符串
	 * @param length 最终需要的字符串长度
	 * @return 填充后的字符串
	 * @author phoenix
	 */
	public static String fillString(String source, String fill, int length){
		if(fill == null || fill.length() == 0 || length < 0) return source;
		StringBuffer filledString = new StringBuffer();
		if(source != null) filledString.append(source);
		int srcLength = 0;
		if(source != null) srcLength = source.length();
		if(srcLength < length) {
			int fillTimes = (length - srcLength) / fill.length();//计算填充次数
			int spareLen = (length - srcLength) % fill.length();//计算剩余填充长度
			for(int i=0;i<fillTimes;i++) filledString.append(fill);
			if(spareLen > 0) filledString.append(fill.substring(0, spareLen));
		}
		return filledString.toString().substring(0, length);
	}
	
	/** 
	 * 获取Map排序后的键集的迭代器
	 * @param map 源Map(其中所有的键皆为字符串)
	 * @param numberKey 源Map中的键是否是数字（如："1","2","3"等）
	 * @return 排序后的键集
	 * @author phoenix
	 */
	public static Iterator getSortedKeyIterator(Map map, boolean numberKey) {
		if(isNullMap(map)) return null;
		try {
			//将键集转换成列表
			List keys = new ArrayList();
			Iterator it = map.keySet().iterator();
			while(it.hasNext()) {
				Object key = it.next();
				if(key instanceof String && numberKey)
					keys.add(new Long((String) key));
				else keys.add(key);
			}
			//排序
			if(numberKey) Collections.sort(keys);
			else Collections.sort(keys, Collator.getInstance());
			return keys.iterator();
		} catch (Exception e) {
			return map.keySet().iterator();
		}
	}
	
	/** 
	 * 检查字符串内容是否为空或者全部由空格组成
	 * @param str 源字符串
	 * @author phoenix
	 */
	public static boolean isNullString(String str) {
		return (str == null || str.trim().equals(""));
	}
	
	/** 
	 * 检查集合内容是否为空
	 * @param list 源列表
	 * @author phoenix
	 */
	public static boolean isNullList(Collection collection) {
		return (collection == null || collection.isEmpty());
	}
	
	/** 
	 * 检查Map内容是否为空
	 * @param map 源Map
	 * @author phoenix
	 */
	public static boolean isNullMap(Map map) {
		return (map == null || map.isEmpty());
	}
	
	/** 
	 * 将源字符串的首字母大写
	 * @param str 源字符串
	 * @author phoenix
	 */
	public static String uppercaseInitiativeLetter(String str) {
		if(isNullString(str)) return "";
		String initiativeLetter = str.trim().substring(0, 1).toUpperCase();//大写首字母
		if(str.trim().length() == 1) return initiativeLetter;
		String otherStr = str.trim().substring(1);
		return initiativeLetter + otherStr;
	}
	
	/** 
	 * 将源字符串的首字母小写
	 * @param str 源字符串
	 * @author phoenix
	 */
	public static String lowercaseInitiativeLetter(String str) {
		if(isNullString(str)) return "";
		String initiativeLetter = str.trim().substring(0, 1).toLowerCase();//小写首字母
		if(str.trim().length() == 1) return initiativeLetter;
		String otherStr = str.trim().substring(1);
		return initiativeLetter + otherStr;
	}
	
	/** 
	 * 将数据库表名转换为数据类名（例如：‘T_CS_SVRQUALITY’转换为‘TCsSvrquality’）
	 * @param tableName 数据库表名
	 * @author phoenix
	 */
	public static String convertTableName(String tableName) {
		return convertTableName(tableName, false);
	}
	
	/** 
	 * 将数据库表名名转换为数据类名（例如：‘T_CS_SVRQUALITY’转换为‘TCsSvrquality’）
	 * @param tableName 数据库表名
	 * @param full 是否转换为完整的类名（例如：“com.greatwall.data.cs.TCsSvrquality”）
	 * @author phoenix
	 */
	public static String convertTableName(String tableName, boolean full) {
		if(isNullString(tableName)) return null;
		String space = "_";//分隔符
		String table = tableName.trim().toLowerCase();
		if(table.indexOf(space) < 0 ) return uppercaseInitiativeLetter(table);
		String[] name = table.split(space);
		StringBuffer packName = new StringBuffer("com.greatwall.data.");
		if(name.length >= 3) packName.append(name[1]).append(".");
		StringBuffer className = new StringBuffer();
		for(int i=0;i<name.length;i++) {
			if(!isNullString(name[i])) 
				className.append(uppercaseInitiativeLetter(name[i]));
		}
		if(full) return packName.toString() + className.toString();
		else return className.toString();
	}
	
	/** 
	 * 将整数转换为字符串（汉字小写模式，例如：110--一百一十）
	 * @param num 目标整数
	 * @author phoenix
	 */
	public static String convertIntToStringInChineseLowMode(int num) {
		switch(num) {
		case 0:return "零";
		case 1:return "一";
		case 2:return "二";
		case 3:return "三";
		case 4:return "四";
		case 5:return "五";
		case 6:return "六";
		case 7:return "七";
		case 8:return "八";
		case 9:return "九";
		}
		
		StringBuffer numString = new StringBuffer();
		if(num < 0) {
			num = num * -1;
			numString.append("负");
		}
		//万位
		int w = num / 10000;
		if(w > 0) {
			numString.append(convertIntToStringInChineseLowMode(w)).append("万");
			num = num % 10000;
		}
		//千位
		int q = num / 1000;
		if(q > 0) {
			numString.append(convertIntToStringInChineseLowMode(q)).append("千");
			num = num % 1000;
		}
		//百位
		int b = num / 100;
		if(b > 0) {
			if(w > 0 && q == 0) numString.append("零");
			numString.append(convertIntToStringInChineseLowMode(b)).append("百");
			num = num % 100;
		}
		//十位
		int s = num / 10;
		if(s > 0) {
			if((w > 0 || q > 0) && b == 0) numString.append("零");
			if(s > 1 || w > 0 || q > 0 || b > 0)
				numString.append(convertIntToStringInChineseLowMode(s));
			numString.append("十");
			num = num % 10;
		}
		//个位
		if(num > 0) {
			if((w > 0 || q > 0 || b > 0) && s == 0) numString.append("零");
			numString.append(convertIntToStringInChineseLowMode(num));
		}
		
		return numString.toString();
	}
	
	/** 
	 * 将整数转换为字符串（汉字大写模式，例如：110--壹百壹拾）
	 * @param num 目标整数
	 * @author phoenix
	 */
	public static String convertIntToStringInChineseUppMode(int num) {
		switch(num) {
		case 0:return "零";
		case 1:return "壹";
		case 2:return "贰";
		case 3:return "叁";
		case 4:return "肆";
		case 5:return "伍";
		case 6:return "陆";
		case 7:return "柒";
		case 8:return "捌";
		case 9:return "玖";
		}
		
		StringBuffer numString = new StringBuffer();
		if(num < 0) {
			num = num * -1;
			numString.append("负");
		}
		//万位
		int w = num / 10000;
		if(w > 0) {
			numString.append(convertIntToStringInChineseUppMode(w)).append("万");
			num = num % 10000;
		}
		//千位
		int q = num / 1000;
		if(q > 0) {
			numString.append(convertIntToStringInChineseUppMode(q)).append("仟");
			num = num % 1000;
		}
		//百位
		int b = num / 100;
		if(b > 0) {
			if(w > 0 && q == 0) numString.append("零");
			numString.append(convertIntToStringInChineseUppMode(b)).append("佰");
			num = num % 100;
		}
		//十位
		int s = num / 10;
		if(s > 0) {
			if((w > 0 || q > 0) && b == 0) numString.append("零");
			numString.append(convertIntToStringInChineseUppMode(s)).append("拾");
			num = num % 10;
		}
		//个位
		if(num > 0) {
			if((w > 0 || q > 0 || b > 0) && s == 0) numString.append("零");
			numString.append(convertIntToStringInChineseUppMode(num));
		}
		
		return numString.toString();
	}
	
	/**
	 * 求和（只支持三种数据类型--Double,Long,String）
	 * @param data1 源数据1
	 * @param data2 源数据2
	 * @return data1 + data2
	 * @author phoenix
	 */
	public static Object add(Object data1, Object data2) throws Exception {
		//检查参数
		if(data1 == null) return data2;
		//求和
		if(data1 instanceof Double) {
			double src = ((Double) data1).doubleValue();
			if(data2 == null) return new Double(src);
			else if(data2 instanceof Number) {
				double sum = ((Number) data2).doubleValue() + src;
				return new Double(sum);
			} else throw null;
		} else if(data1 instanceof Long) {
			long src = ((Long) data1).longValue();
			if(data2 == null) return new Long(src);
			else if(data2 instanceof Number) {
				long sum = ((Number) data2).longValue() + src;
				return new Long(sum);
			} else throw null;
		} else if(data1 instanceof String) {
			String src = (String) data1;
			if(data2 == null) return src;
			else if(data2 instanceof String)
				return data2.toString() + src;
			else throw null;
		} else throw null;
	}
	
	/**
	 * 求差（只支持2种数据类型--Double,Long）
	 * @param data1 源数据1
	 * @param data2 源数据2
	 * @return data1 - data2
	 * @author phoenix
	 */
	public static Object subtract(Object data1, Object data2) throws Exception {
		//检查参数
		if(data2 == null) return data1;
		//求差
		if(data2 instanceof Double) {
			double src = 0d;
			if(data1 instanceof Number) src = ((Number) data1).doubleValue();
			double sum = src - ((Double) data2).doubleValue();
			return new Double(sum);
		} else if(data2 instanceof Long) {
			if(data1 instanceof Double) {
				double src = 0d;
				src = ((Double) data1).doubleValue();
				double sum = src - ((Double) data2).doubleValue();
				return new Double(sum);
			} else {
				long src = 0l;
				if(data1 instanceof Number) src = ((Number) data1).longValue();
				long sum = src - ((Long) data2).longValue();
				return new Long(sum);
			}
		} else throw null;
	}
	
	/**
	 * 求积
	 * @param data1 被乘数（支持2种数据类型--Number,String）
	 * @param multiple 乘数
	 * @return data1 × multiple
	 * @author phoenix
	 */
	public static Double multiple(Object data1, double multiple) {
		try {
			if(data1 instanceof Number)
				return new Double(((Number) data1).doubleValue() * multiple);
			if(data1 instanceof String)
				return multiple(new Double((String) data1), multiple);
		} catch (NumberFormatException e) {
		}
		return null;
	}
	
	/**
	 * 计算两个日期之间的差值
	 * @param date1 源日期1
	 * @param date2 源日期2
	 * @param type 差值类型（年--Calendar.YEAR、月--Calendar.MONTH、日--Calendar.DAY_OF_YEAR）
	 * @author phoenix
	 */
	public static int datediff(Date date1, Date date2, int type) {
		if(date1 == null) date1 = new Date();
		if(date2 == null) date2 = new Date();
		//解析日期
		Calendar c1 = Calendar.getInstance();
		c1.setTime(date1);
		int year1 = c1.get(Calendar.YEAR);
		int month1 = c1.get(Calendar.MONTH);
		int day1 = c1.get(Calendar.DAY_OF_YEAR);
		Calendar c2 = Calendar.getInstance();
		c2.setTime(date2);
		int year2 = c2.get(Calendar.YEAR);
		int month2 = c2.get(Calendar.MONTH);
		int day2 = c2.get(Calendar.DAY_OF_YEAR);
		//计算差值
		int yeardiff = year1 - year2;
		int monthdiff = month1 - month2 + yeardiff * MONTHS_OF_YEAR;
		int daydiff = day1 - day2;
		if(year1 < year2) {
			for(int i=year1;i<year2;i++)
				daydiff -= getDaysOfYear(i);
		} else {
			for(int i=year2;i<year1;i++)
				daydiff += getDaysOfYear(i);
		}
		//返回差值
		if(type == Calendar.YEAR) return yeardiff;
		if(type == Calendar.MONTH) return monthdiff;
		if(type == Calendar.DAY_OF_YEAR) return daydiff;
		return 0;
	}
	
	/**
	 * 判断是否闰年
	 * @param year 年份
	 * @author phoenix
	 */
	private static boolean isSpecialYear(int year) {
		if(year % 4 == 0) {
			if(year % 400 == 0) return true;
			else if(year % 100 == 0) return false;
			else return true;
		} else return false;
	}
	
	/**
	 * 获取某一年中的天数
	 * @param year 年份
	 * @author phoenix
	 */
	private static int getDaysOfYear(int year) {
		if(isSpecialYear(year)) return DAYS_OF_SPECIAL_YEAR;
		else return DAYS_OF_YEAR;
	}	
	/**
	 * 得到年份
	 * @param offset 距离本年的年份,-1为去年,0为本年,1为明年
	 * @author phoenix
	 */
	public static final String getYear(int offset) throws Exception{
		Calendar c=Calendar.getInstance();
		int thisyear=c.get(Calendar.YEAR)+offset;
		return Integer.toString(thisyear);
	}

	/**
	 * 得到年份
	 * @param date 时间对象,如果该值为NULL返回NULL
	 * @author phoenix
	 */
	public static final String getYear(Date date) throws Exception{
		if (date==null) return null;
		Calendar c=Calendar.getInstance();
		c.setTime(date);
		int thisyear=c.get(Calendar.YEAR);
		return Integer.toString(thisyear);
	}
	
	/**
	 * 将HashMap中的KEY的首字母转换为小写
	 * @param map
	 * @author phoenix
	 */
	public static final void covertHashMapToLowerCaseKey(HashMap map){
		if(!CommonUtil.isNullMap(map)) {
	        Iterator it = map.keySet().iterator();
	    	String key;
	    	Object value;
	    	while (it.hasNext()){
				try {
					key = (String) it.next();
					value = map.get(key);
					if (!key.equals(lowercaseInitiativeLetter(key))){
						map.put(lowercaseInitiativeLetter(key), value);
						map.remove(key);
					}
				} catch (Exception e) {
					continue;
				}
	    	}
		}
	}
	
	/**
	 * 判断指定字符串是否在指定字符串数组中
	 * @param items 指定字符串数组
	 * @param item 指定字符串
	 */
	public static boolean contains(String[] items, String item) {
		if(items == null || items.length == 0)
			return false;
		if(item == null) return false;
		for(int i=0;i<items.length;i++)
			if(items[i].equals(item)) return true;
		return false;
	}
	
	/**
	 * 获取最小的未占用的编码(由小写字母a-z或数字0-9组成)
	 * @param occupiedCodes 已占用的编码列表
	 * @param length 编码的长度
	 */
	public static String getMinUnoccupiedCode(List occupiedCodes, int length) {
		//创建构成编码的字母组合，从小到大排列
		char[] letters = new char[36];
		int i = 0;
		for(char ch='0';ch<='9';ch++) letters[i++] = ch;
		for(char ch='a';ch<='z';ch++) letters[i++] = ch;
//		for(char ch='A';ch<='Z';ch++) letters[i++] = ch;
		//遍历已占用的编码列表，找出最小的未占用的编码
		return getMinUnoccupiedCode("", letters, occupiedCodes, length);
	}
	
	/**
	 * 获取最小的未占用的编码(由字母a-Z或数字0-9组成)
	 * @param prefix 编码前缀
	 * @param letters 构成编码的字母组合
	 * @param occupiedCodes 已占用的编码列表
	 * @param length 编码的长度
	 */
	private static String getMinUnoccupiedCode(String prefix, char[] letters, List occupiedCodes, int length) {
		if(prefix.length() >= length) {
			if(occupiedCodes != null && occupiedCodes.contains(prefix)) return null;
			else return prefix;
		}
		for(int i=0;i<letters.length;i++) {
			String code = getMinUnoccupiedCode(prefix + letters[i],
					letters, occupiedCodes, length);
			if(code != null) return code;
		}
		return null;
	}
	
	/**
	 * 将集合组装成字符串
	 * @param collection 集合
	 * @param split 分隔符
	 * @return String 组装好的字符串
	 */
	public static String join(Collection collection, String split) {
		if(isNullList(collection)) return " ";
		else {
			Iterator it = collection.iterator();
			StringBuffer text = new StringBuffer(convertToString(it.next(),""));
			while(it.hasNext()) {
				if(!isNullString(split)) text.append(split);
				text.append(convertToString(it.next(),""));
			}
			return text.toString();
		}
	}
	
	/**
	 * 将传入的字符川安’，‘分割，然后规范输出
	 * 如输入1,2,3,4, 输出 '1','2','3','4'
	 * @param sql
	 */
	public static String organizeSqlString(String sql,String split){
		if(sql == null){
			return "'null'";
		}
		StringBuffer condition = new StringBuffer();
		String[] ids = StringUtils.split(sql, split);
		for (int k = 0; k < ids.length; k++) {
			if(k == ids.length-1){
				condition.append("'" + ids[k] + "'");
			}else{
				condition.append("'" + ids[k] + "',");
			}	
		}
		return condition.toString();
	}
	
	/**
	 * 将传入的字符川安’，‘分割，然后规范输出
	 * 如输入1,2,3,4, 输出 1,2,3,4
	 * @param sql
	 */
	public static String organizeSqlString2(String sql,String split){
		StringBuffer condition = new StringBuffer();
		String[] ids = StringUtils.split(sql, split);
		for (int k = 0; k < ids.length; k++) {
			if(k == ids.length-1){
				condition.append(ids[k]);
			}else{
				condition.append(ids[k] + ",");
			}	
		}
		return condition.toString();
	}
	
	/**
	 * 复制map
	 * @param oldMap
	 * @param newMap
	 */
	public static void copyMap(Map oldMap,Map newMap){
		Set<String> oKeySet = oldMap.keySet();
		for (String string : oKeySet) {
			newMap.put(string, oldMap.get(string));
		}
	}
	
	/**
	 * 编码字符串味base64
	 * @param str
	 */
	public static String encode64(String str){
		if (str == null)
			return null;
		return (new BASE64Encoder()).encode(str.getBytes()); 
	}
	
	/**
	 * 解码base64字符串
	 * @param str
	 * @return
	 * @throws IOException 
	 */
	public static String decode64(String str) throws IOException{
		if (str == null)
			return null;
		BASE64Decoder decoder = new BASE64Decoder();
		byte[] b = decoder.decodeBuffer(str);
		return new String(b);

	}
	/**
	 * 生成随机字符串
	 */
	public static String randomString(){
		String[] num = {"0","1","2","3","4","5","6","7","8","9"};
		String[] cha = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","r","z"};
		String[] cha2 = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
		String[] all = (String[])ArrayUtils.addAll((String[])ArrayUtils.addAll(num, cha), cha2);
		StringBuffer str = new StringBuffer();
		for(int i=0;i<15;i++){
			str.append(all[RandomUtils.nextInt(all.length-1)]);
		}
		return str.toString();
	}
	
	/**
	 * 生成随机字符串
	 */
	public static String randomString(int count){
		String[] num = {"1","2","3","4","5","6","7","8","9"};
		String[] cha1 = {"A","B","C","D","E","F","G","H","J","K","L","M","N","P","Q","R","S","T","U","V","W","X","Y","Z"};
		String[] all = (String[])(String[])ArrayUtils.addAll(num, cha1);
		StringBuffer str = new StringBuffer();
		for(int i=0;i<count;i++){
			str.append(all[RandomUtils.nextInt(all.length-1)]);
		}
		return str.toString();
	}
	
	/**
	 * 生成行程时间列表
	 * @throws Exception
	 */
	public static List<String> makeTimeList() throws Exception{
		List<String> list = new ArrayList<String>();
		String[] hours = {"05","06","07","08","09"};
		for(int i=10;i<=23;i++){
			hours = (String[])ArrayUtils.addAll(hours, new String[]{Integer.toString(i)});
		}
		String[] mins = {"00","10","20","30","40","50"};
		for(int i=0;i<hours.length;i++){
			for(int j=0;j<mins.length;j++){
				list.add(hours[i]+":"+mins[j]);
			}
		}
		return list;
	}
	
	/**
	 * 根据输入的时间寻找行程时间表中适当的时间
	 * @param time 00:00
	 * @return
	 * @throws Exception
	 */
	public static String calTimeByInputTime(String time) throws Exception{
		String[] arr = time.split(":");
		String mi = arr[0];
		String ss = arr[1];
		char[] charArr = ss.toCharArray();
		if(!String.valueOf(charArr[1]).equals("0")){
			return mi+":"+String.valueOf(charArr[0])+"0";
		}else{
			return mi+":"+ss;
		}
		
	}

	/**
	 * 
	 * @param time 12:12
	 * @return
	 */
	public static String makeStringTemplateDate(String day,String time){
		return "2009-08-0"+day+" "+time+":00";
	}
	
	/**
	 * 计算团的天数
	 * @param d1
	 * @param d2
	 * @throws Exception
	 */
	public static int getGroupDateDiff(Date d1,Date d2) throws Exception{
		return Integer.parseInt(Long.valueOf(Math.abs(DateUtil.dateDiffer(d1, d2))).toString())+1;
	}
	
	/**
	 * 过滤参数中非法的字符js html 防止跨站脚本
	 * @param param
	 * @return
	 */
	public static String filterParams(String param){
		return StringEscapeUtils.escapeJavaScript(StringEscapeUtils.escapeHtml(param));
	}
	
}
